package com.example.ercmssystem2.service.impl;

import com.example.ercmssystem2.entity.User;
import com.example.ercmssystem2.entity.Department;
import com.example.ercmssystem2.entity.Event;
import com.example.ercmssystem2.repository.UserRepository;
import com.example.ercmssystem2.repository.DepartmentRepository;
import com.example.ercmssystem2.repository.EventRepository;
import com.example.ercmssystem2.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.HashMap;

@Service
public class UserServiceImpl implements UserService {

    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private DepartmentRepository departmentRepository;
    
    @Autowired
    private EventRepository eventRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        logger.info("尝试加载用户: {}", username);
        
        // 检查用户名是否为空
        if (username == null || username.trim().isEmpty()) {
            logger.warn("用户名为空或空白");
            throw new UsernameNotFoundException("用户名或密码错误");
        }
        
        // 尝试从数据库查找用户
        User user = userRepository.findByUsername(username.trim());
        logger.debug("数据库查询结果: {}", user);
        
        if (user == null) {
            logger.warn("用户不存在: {}", username);
            // 尝试查找所有用户以进行调试
            List<User> allUsers = userRepository.findAll();
            logger.debug("数据库中的所有用户: {}", allUsers.stream().map(User::getUsername).toList());
            throw new UsernameNotFoundException("用户名或密码错误");
        }
        
        logger.info("已找到用户: {}, 角色: {}", username, user.getRole());
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority("ROLE_" + user.getRole()));
        
        // 同时添加没有前缀的权限，以增加兼容性
        authorities.add(new SimpleGrantedAuthority(user.getRole()));
        
        // 详细记录用户信息和权限
        logger.info("用户 {} 的权限: {}", username, authorities);
        logger.info("用户 {} 的密码Hash: {}", username, user.getPassword());
        
        return new org.springframework.security.core.userdetails.User(
            user.getUsername(),
            user.getPassword(),
            user.getEnabled(),
            true, true, true,
            authorities
        );
    }

    @Override
    public User findByUsername(String username) {
        return userRepository.findByUsername(username);
    }

    @Override
    public boolean existsByUsername(String username) {
        return userRepository.existsByUsername(username);
    }

    @Override
    public User getCurrentUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || !authentication.isAuthenticated() || 
            "anonymousUser".equals(authentication.getPrincipal())) {
            return null;
        }
        User user = findByUsername(authentication.getName());
        if (user != null) {
            enrichUserInfo(user);
        }
        return user;
    }

    @Override
    public boolean isSystemAdmin(User user) {
        return user != null && "ADMIN".equals(user.getRole());
    }

    @Override
    public boolean isDeptAdmin(User user) {
        return user != null && "DEPT_MANAGER".equals(user.getRole());
    }

    @Override
    public boolean isDispatcher(User user) {
        return user != null && "DISPATCHER".equals(user.getRole());
    }

    @Override
    public boolean isEndUser(User user) {
        return user != null && "END_USER".equals(user.getRole());
    }

    @Override
    public List<User> getUsersByDepartment(Long departmentId) {
        return userRepository.findByDepartmentIdAndEnabledTrue(departmentId);
    }

    @Override
    public List<User> getDepartmentManagers() {
        return userRepository.findByRoleAndEnabledTrue("DEPT_MANAGER");
    }

    @Override
    public User updateUserDepartment(Long userId, Long departmentId) {
        Optional<User> userOpt = userRepository.findById(userId);
        if (userOpt.isEmpty()) {
            throw new RuntimeException("用户不存在");
        }
        
        User user = userOpt.get();
        user.setDepartmentId(departmentId);
        return userRepository.save(user);
    }

    @Override
    public List<User> getAvailableManagers() {
        return userRepository.findByRoleInAndStatusAndEnabledTrue(List.of("ADMIN", "DEPT_MANAGER", "DISPATCHER", "END_USER"), "AVAILABLE");
    }
    
    @Override
    public List<User> getAvailableUsers() {
        return userRepository.findByStatusAndEnabledTrue("AVAILABLE");
    }
    
    @Override
    public void updateUserStatus(Long userId, String status) {
        Optional<User> userOpt = userRepository.findById(userId);
        if (userOpt.isPresent()) {
            User user = userOpt.get();
            user.setStatus(status);
            user.setUpdatedAt(LocalDateTime.now());
            userRepository.save(user);
        }
    }
    
    @Override
    public boolean isUserAvailable(Long userId) {
        Optional<User> userOpt = userRepository.findById(userId);
        return userOpt.isPresent() && "AVAILABLE".equals(userOpt.get().getStatus()) && userOpt.get().getEnabled();
    }
    
    // Additional methods for UserController
    @Override
    public List<User> findAllUsers() {
        List<User> users = userRepository.findAll();
        users.forEach(this::enrichUserInfo);
        return users;
    }
    
    @Override
    public User findById(Long id) {
        User user = userRepository.findById(id).orElse(null);
        if (user != null) {
            enrichUserInfo(user);
        }
        return user;
    }
    
    @Override
    public List<User> findByDepartmentId(Long departmentId) {
        List<User> users = userRepository.findByDepartmentIdAndEnabledTrue(departmentId);
        users.forEach(this::enrichUserInfo);
        return users;
    }
    
    @Override
    public List<User> findByRole(String role) {
        List<User> users = userRepository.findByRoleAndEnabledTrue(role);
        users.forEach(this::enrichUserInfo);
        return users;
    }
    
    @Override
    public List<User> findByDepartmentIds(List<Long> departmentIds) {
        List<User> users = userRepository.findByDepartmentIdInAndEnabledTrue(departmentIds);
        users.forEach(this::enrichUserInfo);
        return users;
    }
    
    @Override
    public User saveUser(User user) {
        // 如果是新用户，设置创建时间
        if (user.getId() == null) {
            user.setCreatedAt(LocalDateTime.now());
        }
        
        // 设置更新时间
        user.setUpdatedAt(LocalDateTime.now());
        
        // 如果密码不为空且不是已加密的密码，则加密
        if (user.getPassword() != null && !user.getPassword().startsWith("$2a$")) {
            user.setPassword(passwordEncoder.encode(user.getPassword()));
        }
        
        User savedUser = userRepository.save(user);
        enrichUserInfo(savedUser);
        return savedUser;
    }
    
    @Override
    public void deleteUser(Long id) {
        User user = userRepository.findById(id).orElse(null);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        
        try {
            // 检查用户是否正在处理事件
            List<Event> userEvents = eventRepository.findByHandler(user);
            if (!userEvents.isEmpty()) {
                // 如果用户正在处理事件，先释放这些事件
                for (Event event : userEvents) {
                    event.setHandler(null);
                    event.setStatus("PENDING");
                    eventRepository.save(event);
                }
            }
            
            // 检查用户是否是部门管理员
            List<Department> managedDepartments = departmentRepository.findByManagerIdAndEnabledTrue(id);
            if (!managedDepartments.isEmpty()) {
                // 如果用户是部门管理员，先移除管理关系
                for (Department dept : managedDepartments) {
                    dept.setManagerId(null);
                    departmentRepository.save(dept);
                }
            }
            
            // 删除用户（由于设置了级联删除，相关的记录会自动删除）
            userRepository.deleteById(id);
        } catch (Exception e) {
            System.err.println("删除用户失败: " + e.getMessage());
            throw new RuntimeException("删除用户失败: " + e.getMessage());
        }
    }

    // 私有方法：丰富用户信息
    private void enrichUserInfo(User user) {
        if (user.getDepartmentId() != null) {
            Optional<Department> department = departmentRepository.findById(user.getDepartmentId());
            department.ifPresent(dept -> user.setDepartmentName(dept.getName()));
        }
    }
    
    // ========== 统计分析相关方法实现 ==========
    
    @Override
    public Map<String, Object> getPersonnelPerformanceStatistics(LocalDateTime start, LocalDateTime end) {
        Map<String, Object> stats = new HashMap<>();
        
        // 获取所有用户
        List<User> allUsers = userRepository.findAll();
        
        // 人员状态概览
        Map<String, Long> statusDistribution = allUsers.stream()
            .filter(User::getEnabled)
            .collect(Collectors.groupingBy(User::getStatus, Collectors.counting()));
        stats.put("statusDistribution", statusDistribution);
        
        // 按角色统计
        Map<String, Long> roleDistribution = allUsers.stream()
            .filter(User::getEnabled)
            .collect(Collectors.groupingBy(User::getRole, Collectors.counting()));
        stats.put("roleDistribution", roleDistribution);
        
        // 按部门统计
        Map<String, Long> departmentDistribution = allUsers.stream()
            .filter(User::getEnabled)
            .filter(u -> u.getDepartmentId() != null)
            .collect(Collectors.groupingBy(u -> {
                Optional<Department> dept = departmentRepository.findById(u.getDepartmentId());
                return dept.map(Department::getName).orElse("未知部门");
            }, Collectors.counting()));
        stats.put("departmentDistribution", departmentDistribution);
        
        // 人员工作量统计（基于事件处理）
        Map<String, Object> workloadStats = new HashMap<>();
        for (User user : allUsers) {
            if (user.getEnabled()) {
                // 获取用户处理的事件
                List<Event> userEvents = eventRepository.findByHandlerIdAndCreatedAtBetweenOrderByCreatedAtDesc(
                    user.getId(), start, end);
                
                // 计算工作量指标
                long totalEvents = userEvents.size();
                long completedEvents = userEvents.stream()
                    .filter(e -> "COMPLETED".equals(e.getStatus()) || "RESOLVED".equals(e.getStatus()))
                    .count();
                
                // 计算平均响应时间
                double avgResponseTime = userEvents.stream()
                    .filter(e -> e.getResponseTimeMinutes() != null)
                    .mapToLong(Event::getResponseTimeMinutes)
                    .average()
                    .orElse(0.0);
                
                // 计算平均处置时间
                double avgProcessingTime = userEvents.stream()
                    .filter(e -> e.getProcessingTimeMinutes() != null)
                    .mapToLong(Event::getProcessingTimeMinutes)
                    .average()
                    .orElse(0.0);
                
                Map<String, Object> userStats = new HashMap<>();
                userStats.put("totalEvents", totalEvents);
                userStats.put("completedEvents", completedEvents);
                userStats.put("completionRate", totalEvents > 0 ? (double) completedEvents / totalEvents * 100 : 0.0);
                userStats.put("avgResponseTime", avgResponseTime);
                userStats.put("avgProcessingTime", avgProcessingTime);
                userStats.put("userName", user.getRealName());
                userStats.put("role", user.getRole());
                
                workloadStats.put(user.getId().toString(), userStats);
            }
        }
        stats.put("workloadStats", workloadStats);
        
        // 调度员工作量统计
        List<User> dispatchers = allUsers.stream()
            .filter(u -> "DISPATCHER".equals(u.getRole()) && u.getEnabled())
            .collect(Collectors.toList());
        
        Map<String, Object> dispatcherStats = new HashMap<>();
        for (User dispatcher : dispatchers) {
            // 统计调度员处理的事件数量
            long dispatchedEvents = eventRepository.countByHandlerId(dispatcher.getId());
            dispatcherStats.put(dispatcher.getRealName(), dispatchedEvents);
        }
        stats.put("dispatcherStats", dispatcherStats);
        
        // 人员可用性统计
        long totalActiveUsers = allUsers.stream().filter(User::getEnabled).count();
        long availableUsers = statusDistribution.getOrDefault("AVAILABLE", 0L);
        long busyUsers = statusDistribution.getOrDefault("BUSY", 0L);
        long offlineUsers = statusDistribution.getOrDefault("OFFLINE", 0L);
        
        double availabilityRate = totalActiveUsers > 0 ? (double) availableUsers / totalActiveUsers * 100 : 0.0;
        double busyRate = totalActiveUsers > 0 ? (double) busyUsers / totalActiveUsers * 100 : 0.0;
        double offlineRate = totalActiveUsers > 0 ? (double) offlineUsers / totalActiveUsers * 100 : 0.0;
        
        stats.put("totalActiveUsers", totalActiveUsers);
        stats.put("availableUsers", availableUsers);
        stats.put("busyUsers", busyUsers);
        stats.put("offlineUsers", offlineUsers);
        stats.put("availabilityRate", availabilityRate);
        stats.put("busyRate", busyRate);
        stats.put("offlineRate", offlineRate);
        
        return stats;
    }
} 